package com.jumi.microservice.order.handler;

import com.alibaba.fastjson.JSON;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.bean.ProducerBean;
import com.jumi.microservice.common.utils.DateUtil;
import com.jumi.microservice.config.TimeConfiguration;
import com.jumi.microservice.dto.order.OrderLogRequest;
import com.jumi.microservice.entity.OrderGoods;
import com.jumi.microservice.entity.UserOrder;
import com.jumi.microservice.enumerate.OrderTypeEnum;
import com.jumi.microservice.mapper.OrderGoodsMapper;
import com.jumi.microservice.mapper.UserOrderMapper;
import com.jumi.microservice.order.context.GoodsSkuContext;
import com.jumi.microservice.order.context.OrderCreateContext;
import com.jumi.microservice.order.context.TransHandlerContext;
import com.jumi.microservice.service.IOrderDubboService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

/**
 * @author Dirk
 * @Date 2020-08-04 17:40
 */
@Component
public class OrderCreateLogisticalHandler implements TransHandler {

    private static final Logger log = LoggerFactory.getLogger(TransHandler.class);

    @Resource
    private UserOrderMapper userOrderMapper;

    @Resource
    private OrderGoodsMapper orderGoodsMapper;

    @DubboReference
    private IOrderDubboService orderDubboService;

    @Resource
    ProducerBean producerBean;
    @Resource
    TimeConfiguration timeConfiguration;

    @Override
    public boolean isAsync() {
        return false;
    }

    @Override
    public boolean handler(TransHandlerContext context) {
        OrderCreateContext ctx = (OrderCreateContext) context;
        log.info("创建订单时上下文参数: [{}]", JSON.toJSONString(ctx));
        String sn = generateOrderSn();
        ctx.setOrderSn(sn);
        ctx.setPayNo(sn);
        List<OrderCreateContext> childOrderContextList = ctx.getChildOrderContextList();
        boolean result = true;
        for (OrderCreateContext orderCreateContext : childOrderContextList) {
            orderCreateContext.setOrderSn(generateOrderSn());
            orderCreateContext.setPayNo(sn);
//            orderCreateContext.setRemarks(orderCreateContext.getGoodsList()
//                    .stream().map(GoodsSkuContext::getRemarks).collect(Collectors.joining()));
            orderCreateContext.setRemarks(orderCreateContext.getGoodsList().get(0).getRemarks());
            result &= createOrder(orderCreateContext);
            //发送创建订单消息队列
            Message message = new Message("unPay", "", "", JSON.toJSONBytes(orderCreateContext));
            message.setStartDeliverTime(DateUtil.getDateAfterMinute(new Date(),
                    Integer.parseInt(timeConfiguration.getWaitPaySendMessageMinutes())).getTime());
            producerBean.send(message);

            // 记录日志
            OrderLogRequest orderLogRequest = new OrderLogRequest();
            orderLogRequest.setOrderSn(orderCreateContext.getOrderSn());
            orderLogRequest.setUserFlag(new Byte("1"));
            orderLogRequest.setOperatorId(orderCreateContext.getUid());
            orderLogRequest.setOperatorName("买家");
            orderLogRequest.setLog("创建订单-".concat(orderCreateContext.getOrderSn()));
            orderDubboService.addOrderLog(orderLogRequest);
        }
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean createOrder(TransHandlerContext context) {
        OrderCreateContext ctx = (OrderCreateContext) context;
        List<GoodsSkuContext> goodsSkuContextList = ctx.getGoodsList();
        UserOrder userOrder = new UserOrder();
        userOrder.setOrderNo(ctx.getOrderSn());
        userOrder.setBuyerId(ctx.getUid());
        userOrder.setBuyerRole(ctx.getUserRole());
        userOrder.setOrderStatus(ctx.getOrderStatus().getCode());
        userOrder.setOrderType(ctx.getOrderType() == null ? OrderTypeEnum.USER_CREATE.getCode() : ctx.getOrderType());
        userOrder.setOrderPromotionAmount(goodsSkuContextList.stream()
                .map(goodsSkuContext -> goodsSkuContext.getGoodsPromotionPrice()
                        .multiply(new BigDecimal(goodsSkuContext.getGoodsAmount())))
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        userOrder.setFreightFee(goodsSkuContextList.stream()
                .map(GoodsSkuContext::getGoodsFreightFee)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        userOrder.setOrderAmount(goodsSkuContextList.stream()
                .map(goodsSkuContext -> goodsSkuContext.getGoodsPrice()
                        .multiply(new BigDecimal(goodsSkuContext.getGoodsAmount())))
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        userOrder.setPayAmount(ctx.getOrderAmount().add(ctx.getFreightFee()));
        userOrder.setPayNo(ctx.getPayNo());
        userOrder.setFailureTime(DateUtil.getDateAfterMinute(new Date(),Integer.parseInt(timeConfiguration.getFailPayMinutes())));
        userOrder.setReceiverName(ctx.getReceiverName());
        userOrder.setReceiverPhone(ctx.getReceiverPhone());
        userOrder.setReceiverAddress(ctx.getReceiverAddress());
        userOrder.setRemark(ctx.getRemarks());
        userOrder.setInvoiceId(ctx.getInvoiceId());
        if(ctx.getInviteId()!=null && !ctx.getInviteId().equals(ctx.getUid())){
            userOrder.setInviteId(ctx.getInviteId());
        }
        userOrder.setClientIp(ctx.getClientIp());
        userOrder.setPlatformType(ctx.getPlatformType());
        userOrder.setImpRealName(ctx.getImpRealName());
        userOrder.setImpCardNo(ctx.getImpCardNo());
        int i = userOrderMapper.insert(userOrder);
        List<OrderGoods> orderGoodsList = new ArrayList<>();
        ctx.getGoodsList().forEach(goodsSku -> {
            OrderGoods orderGoods = new OrderGoods();
            orderGoods.setOrderId(userOrder.getId());
            orderGoods.setOrderNo(userOrder.getOrderNo());
            orderGoods.setGoodsId(goodsSku.getGoodsId());
            orderGoods.setSpuId(goodsSku.getSpuId());
            orderGoods.setIsGroup(goodsSku.getIsGroup());
            orderGoods.setSelfFlag(goodsSku.getSelfFlag());
            orderGoods.setGoodsName(goodsSku.getGoodsName());
            orderGoods.setGoodsSpec(goodsSku.getGoodsSpec());
            orderGoods.setGoodsAmount(goodsSku.getGoodsAmount());
            orderGoods.setGoodsPromotionPrice(goodsSku.getGoodsPromotionPrice());
            orderGoods.setGoodsPlatinumPrice(goodsSku.getGoodsPlatinumPrice());
            orderGoods.setGoodsDiamondsPrice(goodsSku.getGoodsDiamondsPrice());
            orderGoods.setGoodsKingPrice(goodsSku.getGoodsKingPrice());
            orderGoods.setGoodsCostPrice(goodsSku.getGoodsCostPrice());
            orderGoods.setGoodsGainPrice(goodsSku.getGainPrice());
            orderGoods.setGoodsPrice(goodsSku.getGoodsPrice());
            orderGoods.setGoodsLabel(goodsSku.getGoodsLabel());
            orderGoods.setGoodsWeight(goodsSku.getGoodsWeight());
            orderGoods.setGoodsFreightFee(goodsSku.getGoodsFreightFee());
            orderGoods.setGoodsCoverImg(goodsSku.getGoodsCoverImg());
            orderGoods.setDrainage(goodsSku.getDrainage());
            orderGoods.setFixRebate(goodsSku.getFixRebate());
            orderGoods.setIsImport(goodsSku.getIsImport());
            orderGoods.setVerifyStatus(goodsSku.getVerifyStatus());
            orderGoods.setShouldWarehouse(goodsSku.getShouldWarehouse() == null ? 0 : goodsSku.getShouldWarehouse());
            orderGoods.setRealWarehouse(goodsSku.getRealWarehouse() == null ? 0 : goodsSku.getRealWarehouse());
            orderGoods.setSupplierId(goodsSku.getSupplierId());
            orderGoods.setWarehouseSn(goodsSku.getWarehouseSn());
            orderGoods.setFreeGoods(goodsSku.getFreeGoods());
            orderGoods.setActivityId(goodsSku.getActivityId());
            orderGoods.setActivityType(goodsSku.getActivityType());
            orderGoodsList.add(orderGoods);
        });
        int j = orderGoodsMapper.batchInsert(orderGoodsList);

        return i > 0 && j > 0;
    }

    /**
     * 生成全局唯一订单号
     *
     * @return orderSn
     */
    private String generateOrderSn() {
        String time = DateUtil.getAllMSTime();
        return time.substring(2) + ThreadLocalRandom.current().nextInt(1000, 10000);
    }
}
